#include <iostream>
#include <stdexcept>
#include <string>
#include <cstring>
#include <sstream>
#include "item.h"
#include "mapitem.h"
#include <vector>
#include "SDL.h"
#include "SDL_image.h"
#include "character.h"
#include "location.h"
#include "mapitemfactory.h"

using namespace std;

Location::Location() throw(location_error){
	name_= "";
	description_= "";
	restrictions_ = "";
	items_ = "";
	locations_ = "";
	itemsObj_.clear();
	
	MapItemFactory *factory = new MapItemFactory();
	
	try
	{
		for(int y = 0; y < 44 ; y++)
		{
			for(int x = 0; x < 17 ; x++)
			{
				// Fill the map with standard tiles
				map_[x][y] = factory->build("maptile");
				
			}
		}
	}
	catch(mapitemfactory_error &texterror)
	{
		cout << texterror.what();
		throw location_error("location: Could not create location!");
	}
	
	delete factory;
}

Location::~Location(){
       for(int y = 0; y < 44 ; y++)
       {
	      for(int x = 0; x < 17 ; x++)
	      {
		     delete map_[x][y];
	      }
       }
}

// Functions to set all data in a Location node
void Location::setName(string name){
       name_ = name;
}

void Location::setDescription(string description){
	description_ = description;
}

void Location::setRestrictions(string restrictions){
	restrictions_ = restrictions;
}
       
void Location::setLocations(string locations){
	locations_ = locations;
}

void Location::addRestriction(string restriction){
	restrictions_ = restrictions_ + " " + restriction;
}

void Location::addItem(Item* item){

	// Add itemNumber last to the items string
	items_ = items_ + " " + item->getId();
	
	// Add item object to vector containing the locations items.
	itemsObj_.push_back(item);
}

void Location::addLocation(string location){
	locations_ = locations_ + " " + location;
}

// Functions to get all data from a Location node
string Location::getName(){
       return name_;
}

string Location::getDescription(){
       return description_;
}

string Location::getRestrictions(){
       return restrictions_;
}

string Location::getItems(){
       return items_;
}

string Location::getLocations(){
       return locations_;
}

string Location::findRestrictions(Character& me){
	string foundRestrictions = "";
	string getRestriction = "";
	istringstream is;
	
	if(restrictions_ != "")
	{
		is.str(restrictions_);

		// Find each restriction (item) which the character is not carrying and add to foundRestrictions
		while(is >> getRestriction)
		{
			if(!me.find(getRestriction))
			{
				if(foundRestrictions == "")
				{
					foundRestrictions = foundRestrictions + getRestriction;
				}
				else
				{
					foundRestrictions = foundRestrictions + " " + getRestriction;
				}
			}
				
			
		}
		
	}
	
	return foundRestrictions;
}

// Check if item exists in location 
bool Location::findItem(Item* item){
	bool found = false;
	
	// Go through all items
	for(int i = 0; i < itemsObj_.size() && found == false; i++)
	{
		if(itemsObj_[i]->getId() == item->getId())
			found = true;
	}
	
	return found;
}

void Location::removeItem(Item* item){
	string holdItem = "";
	string newItemsList = "";
	bool removed = false;

	// Get item id to remove
	string toRemove = item->getId();
	
	// Remove item from items_	
	istringstream fromItems;
	fromItems.str(items_);
	
	// Remove once instance of the item id
	while(fromItems >> holdItem)
	{
		if(holdItem == toRemove && removed == false)
		{
			removed = true;
		}
		else
		{
			if(newItemsList == "")
			{
				newItemsList = holdItem;
			}
			else
			{
				newItemsList = newItemsList + " " + holdItem;
			}
		}
	}
	
	items_ = newItemsList;
	
	if(!removed)
	{
		cout << "There is no " << toRemove << " there.\n";
	}
	else
	{
		removed = false;

		// Remove the item object from itemObj_
		for(int i = 0; i < itemsObj_.size() && removed == false; i++)
		{
			if(itemsObj_[i]->getId() == toRemove)
			{
				itemsObj_.erase(itemsObj_.begin()+i);
				removed = true;
			}
			
		}

		if(removed == false)
		{
			cout << "The item was removed from items_ char, but not from itemsObj_, this is not supposed to happend!" << endl;
		}
	}
}

void Location::removeRestriction(string restriction){
	string newRestrictionsList = "";
	string getRestriction = "";
	bool removed = false;
	istringstream is;
	is.str(restrictions_);
	
	// Remove one instance of the restriction
	while(is >> getRestriction)
	{
		if(getRestriction == restriction && removed == false)
		{
			removed = true;
		}
		else
		{
			if(newRestrictionsList == "")
			{
				newRestrictionsList = getRestriction;	
			}
			else
			{
				newRestrictionsList = newRestrictionsList + " " + getRestriction;
			}
		}
	}

	restrictions_ = newRestrictionsList;
}

// Return an Item* to an object with the correct item id
Item* Location::getItem(string item)
{
	bool found = false;
	
	for(int i = 0; i < itemsObj_.size() && found == false; i++)
	{
		if(itemsObj_[i]->getId() == item)
		{
			return itemsObj_[i];
		}
	}
	
	return 0;
}